package org.example.batch;

import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;

/**
 * 大数据量批处理任务执行监听器 - 教学版本
 * 
 * JobExecutionListener 是 Spring Batch 提供的监听器接口，用于监听Job的生命周期
 * 
 * 监听器的作用：
 * 1. 任务开始前的准备工作：初始化资源、重置统计信息等
 * 2. 任务结束后的清理工作：释放资源、输出统计信息、发送通知等
 * 3. 性能监控：记录任务执行时间、处理记录数等关键指标
 * 4. 错误处理：在任务失败时进行特殊处理
 * 5. 业务通知：向相关人员发送任务完成通知
 * 
 * 实际应用场景：
 * - 大数据ETL任务的监控和统计
 * - 任务执行日志记录
 * - 性能指标收集
 * - 异常情况报警
 * - 业务方通知
 * 
 * @author example
 */
public class BigDataJobExecutionListener implements JobExecutionListener {

    /**
     * 任务开始前执行
     * 
     * 这个方法在Job开始执行前被调用，适合做以下工作：
     * - 初始化全局资源
     * - 重置统计计数器
     * - 记录任务开始时间
     * - 发送任务开始通知
     * - 预处理工作（如创建临时表、清理旧数据等）
     * 
     * @param jobExecution Job执行上下文，包含Job的详细信息
     */
    @Override
    public void beforeJob(JobExecution jobExecution) {
        String separator = "============================================================";
        System.out.println("\n" + separator);
        System.out.println("🚀 大数据量学生批处理任务开始执行");
        System.out.println(separator);
        
        // 获取Job基本信息
        String jobName = jobExecution.getJobInstance().getJobName();
        Long jobId = jobExecution.getJobId();
        String startTime = jobExecution.getStartTime().toString();
        
        System.out.println("任务名称: " + jobName);
        System.out.println("任务ID: " + jobId);
        System.out.println("开始时间: " + startTime);
        
        // 获取Job参数
        System.out.println("任务参数:");
        jobExecution.getJobParameters().getParameters().forEach((key, value) -> {
            System.out.println("  " + key + " = " + value.getValue());
        });
        
        // 重置处理器的统计信息
        BigDataStudentProcessor.resetStatistics();
        
        System.out.println("\n📊 准备开始处理学生数据...");
        System.out.println("💡 提示：可以观察控制台输出了解处理进度");
        System.out.println("------------------------------------------------------------\n");
    }

    /**
     * 任务结束后执行
     * 
     * 这个方法在Job执行完成后被调用，无论成功还是失败都会执行
     * 适合做以下工作：
     * - 输出最终统计信息
     * - 清理临时资源
     * - 发送完成通知
     * - 记录任务执行结果
     * - 错误处理和报警
     * 
     * @param jobExecution Job执行上下文，包含Job的执行结果
     */
    @Override
    public void afterJob(JobExecution jobExecution) {
        String dashSeparator = "------------------------------------------------------------";
        System.out.println("\n" + dashSeparator);
        System.out.println("📋 大数据量学生批处理任务执行完成");
        System.out.println(dashSeparator);
        
        // 获取执行结果信息
        String jobName = jobExecution.getJobInstance().getJobName();
        Long jobId = jobExecution.getJobId();
        String status = jobExecution.getStatus().toString();
        String exitStatus = jobExecution.getExitStatus().getExitCode();
        
        // 计算执行时间
        long startTime = jobExecution.getStartTime().getTime();
        long endTime = jobExecution.getEndTime().getTime();
        long duration = endTime - startTime;
        
        System.out.println("任务名称: " + jobName);
        System.out.println("任务ID: " + jobId);
        System.out.println("执行状态: " + status);
        System.out.println("退出状态: " + exitStatus);
        System.out.println("总执行时间: " + duration + " ms (" + (duration / 1000.0) + " 秒)");
        
        // 输出Step执行信息
        System.out.println("\nStep执行信息:");
        jobExecution.getStepExecutions().forEach(stepExecution -> {
            System.out.println("  Step名称: " + stepExecution.getStepName());
            System.out.println("  读取记录数: " + stepExecution.getReadCount());
            System.out.println("  处理记录数: " + (stepExecution.getReadCount() - stepExecution.getFilterCount()));
            System.out.println("  写入记录数: " + stepExecution.getWriteCount());
            System.out.println("  跳过记录数: " + stepExecution.getSkipCount());
            System.out.println("  提交次数: " + stepExecution.getCommitCount());
            System.out.println("  回滚次数: " + stepExecution.getRollbackCount());
            
            if (stepExecution.getFilterCount() > 0) {
                System.out.println("  过滤记录数: " + stepExecution.getFilterCount());
            }
            
            if (stepExecution.getReadSkipCount() > 0 || 
                stepExecution.getProcessSkipCount() > 0 || 
                stepExecution.getWriteSkipCount() > 0) {
                System.out.println("  读取跳过: " + stepExecution.getReadSkipCount());
                System.out.println("  处理跳过: " + stepExecution.getProcessSkipCount());
                System.out.println("  写入跳过: " + stepExecution.getWriteSkipCount());
            }
        });
        
        // 输出自定义统计信息
        BigDataStudentProcessor.printStatistics();
        
        // 根据执行状态输出不同的信息
        if ("COMPLETED".equals(status)) {
            System.out.println("✅ 任务执行成功！");
            
            // 计算性能指标
            long totalRecords = jobExecution.getStepExecutions().stream()
                    .mapToLong(step -> step.getReadCount())
                    .sum();
            
            if (totalRecords > 0 && duration > 0) {
                double recordsPerSecond = totalRecords * 1000.0 / duration;
                System.out.println("📈 整体处理性能: " + String.format("%.2f", recordsPerSecond) + " 记录/秒");
            }
            
            // 实际应用中，这里可以：
            // - 发送成功通知邮件
            // - 更新任务调度状态
            // - 触发下游任务
            // - 更新数据质量报告
            
        } else if ("FAILED".equals(status)) {
            System.out.println("❌ 任务执行失败！");
            
            // 输出失败原因
            jobExecution.getAllFailureExceptions().forEach(throwable -> {
                System.err.println("失败原因: " + throwable.getMessage());
            });
            
            // 实际应用中，这里可以：
            // - 发送失败报警邮件
            // - 记录错误日志到监控系统
            // - 触发重试机制
            // - 回滚相关数据
            
        } else {
            System.out.println("⚠️  任务执行状态: " + status);
        }
        
        String finalSeparator = "============================================================";
        System.out.println("\n" + finalSeparator);
        System.out.println("📊 大数据量批处理任务报告完成");
        System.out.println(finalSeparator + "\n");
    }
} 